#pragma once

#pragma once

#include <base.h>
#include <dbg.h>
/* apds内部使用的核心感知信息 */
typedef struct apdstinfo{
	tid_t tid;	/* tid */
	cid_t cid;	/* 当前cid */
} apdstinfo_t;

/* 定义OUFUN */

STA_OUFUN(apdstinfo)
apdstinfo_t * (* const get)();
void (* const upd)();
END_OUFUN(apdstinfo)

/* 操作系统下的tls 形式, 稍微有点麻烦 */
#include <dinfra/mplf/tstack.h>
/* 大体是一个slab式的分配 */
typedef struct apdstls{
	/* meta信息 */
	tsnode_t	node;
	apdstinfo_t	tinfo;
	word_t		cid_updcnt;

	void		*free_list;
} apdstls_t;


/* 释放接口 */
SAI void _apdstls_freetls(tstack_t *tlstk, apdstls_t *p){
	// 挂到链表里
	tstack_push(tlstk, &p->node);
}
/* 由用户申请和释放 */
SAI apdstls_t *_apdstls_init(void *ptr, word_t size, cid_t tid, cid_t cid){
	ASSERT(ptr);
	apdstls_t *p = (apdstls_t *)ptr;
	__memset(p, 0, size);
	// 分配alloca
	p->tinfo.tid = tid;
	p->tinfo.cid = cid;
	p->free_list = NULL;
	p->cid_updcnt = 0;
	// 注册
	return p;
}
SAI cid_t _apdstls_updcid(apdstls_t *l, const word_t freq, cid_t (*apds_coreid) () ){
	ASSERT(is_powerof2(freq));
	if (l->cid_updcnt++ % freq == 0){
		l->tinfo.cid = apds_coreid();
	}
	return l->tinfo.cid;
}

SAI apdstls_t *_apdstls_tryalloctls(tstack_t *tlstk){
	tsnode_t *nd = tstack_pop(tlstk);
	if (!nd) return NULL;
	apdstls_t *l = tstack_entry(nd, apdstls_t, node);
	return l;
}

#define DECL_APDS_THREADNR					\
HIDDEN cid_t __apfsds_cur_threads = 0;					\
HIDDEN cid_t __max_threads = 0;					\
SAI cid_t _apdstls_add_threadnr(){				\
	return faa(&__max_threads, 1);				\
}\
SAI cid_t _apdstls_decr_threadnr(){				\
	return fas(&__max_threads, 1);				\
}\
SAI tid_t apdstls_maxtid(){ return __max_threads; }

/*
	需要用户定义size, malloctls接口, cidupd_freq以及get_coreid接口
*/
#define DEF_APDSTINFO_TLS(tlstk, ptls, malloctls, cidupd_freq, apds_coreid)	\
DECL_APDS_THREADNR								\
SAI RETURN_NONULL apdstinfo_t *apdstls_get(){ ASSERT(*(ptls)); return &((*(ptls))->tinfo); }\
SAI void apdstls_upd(){ _apdstls_updcid(*(ptls), cidupd_freq, apds_coreid); }	\
CFLOWFIN_FUNC(apdstls) { INFO("[%u]free apds, cur threads %u\n", (*(ptls))->tinfo.tid, __apfsds_cur_threads); /* _apdstls_decr_threadnr(); */ fas(&__apfsds_cur_threads, 1); _apdstls_freetls(tlstk, *(ptls)); }			\
CFLOWINIT_FUNC(apdstls){							\
	apdstls_t *p = _apdstls_tryalloctls(tlstk);				\
	/* tid_t tmp_tid = _apdstls_add_threadnr(); */				\
	INFO("apdstls cflow init\n");						\
	faa(&__apfsds_cur_threads, 1);							\
	if (!p) {								\
		tid_t tmp_tid = _apdstls_add_threadnr();			\
		p = _apdstls_init(malloctls(sizeof(apdstls_t)), sizeof(apdstls_t), tmp_tid, apds_coreid());\
		/*INFO("[%u]apdstls\n", p->tinfo.tid);*/			\
	}									\
	ASSERT(p);								\
	*(ptls) = p;								\
	_apdstls_updcid(p, cidupd_freq, apds_coreid);				\
	p->cid_updcnt = 0;/* 一开始执行时还是需要获得一次 */			\
}										\
SYSINIT_FUNC(apdstls){ INFO("apdstls sysinit\n"); }				\
MAY_UNUSED NEW_OUFUN(apdstinfo, apdstls, apdstls_get, apdstls_upd)
